<?php if ( ! defined('BASEPATH')) exit('This file does not run directly. Sorry.'); ?>
<?php
/**
 * Kalaisoo.
 *
 * A lightweight no-framework framework written in PHP.
 *
 * @package Kalaisoo
 * @author $Author: info@sah-company.com $
 * @version $Id: user.php 142 2012-01-24 22:24:34Z info@sah-company.com $
 */

/**
 * Kalaisoo User Controller Class.
 *
 * This is the user controller of our framework. It has methods and views to let users login
 * or logout, request a new password, edit his or her account data.
 *
 * @package Kalaisoo
 * @subpackage Controller
 * @author $Author: info@sah-company.com $
 * @see sys/core/refused.php class Controller
 */
class User_Controller extends Controller
{
	/**
	 * number of records to load at once
	 */
	const LIMIT_RECORDS = 24;

	/**
	 * constructs a new User controller.
	 */
	public function __construct()
	{
		parent::__construct();
		$this->init();
	}
	
	/**
	 * starts a session, loads needed models, language files and so on.
	 */
	protected function init()
	{
		session_start();
		$_SESSION['lastActivity'] = time();
		$this->registry->cache->setLifetime(0);
		$this->registry->loader->lib(array('redbean', 'permission'));
		$this->registry->loader->model('user');
		$this->registry->loader->language('user');
		$this->registry->loader->helper(array('url', 'textile'));
		$this->permission = new Permission();
		$this->template = new Template();
		$this->input = new Input();
		$this->user = R::dispense('user');
		$this->data['scripts'][] = 'jquery/jquery-1.6.2.min';
		$this->data['scripts'][] = 'core';
		$this->data['locale']['date_format'] = '%a., %e. %B %Y';
		$this->data['locale']['time_format'] = '%H:%M';
		setlocale(LC_TIME, $this->registry->config['locale'][$this->registry->language]);
		$this->registry->addBreadcrumb(__('home'), sprintf('%s/user/index/', $this->registry->language));
	}
	
	/**
	 * checks if the current user session is authenticated and loads the user bean or redirects.
	 *
	 * If the current session is authenticated the current user is loaded.
	 * Otherwise client is redirected to login with the current url as a referer.
	 */
	protected function auth()
	{
		if ( ! $this->user->isAuth()) {
			return $this->redirect(ahref(sprintf('%s/user/login/?goto=%s', $this->registry->language, urlencode($this->registry->router->url()))));
		}
		$this->user = R::load('user', $_SESSION['auth']);
		$this->data['user'] = $this->user;
	}
	
	/**
	 * displays the blog entries or adds a new blog bean when user posted a form.
	 *
	 * @todo use Editor for a new blog entry
	 * @todo get rid of redirect, use ajax maybe
	 * @todo refactor code for loading blog entries
	 *
	 * @param int Starting point of record index
	 * @param int Limit number of records to show
	 */
	public function blog($limitOffset = 0, $limitFind = self::LIMIT_RECORDS)
	{
		$this->auth();
		$this->data['styles'][] = 'blog';
		if ( ! $this->permission->granted($this->user, 'index', 'user')) {
			return $this->error(__('error_no_permission'));
		}
		
		$this->registry->loader->language('blog');
		// load user
		$blog = R::dispense('blog');
		// was a form sent
		if ($this->input->submit) {
			$blog->import($this->input->blog);
			if ( ! isset($blog->content) || empty($blog->content)) {
				$this->data['errors']['fn_content'] = __('blog_content_missing');
			}
			else {
				try {
					$blog->stamp = time();
					$blog->location = $this->user->location;
					R::store($blog);
					R::associate($this->user, $blog);
					$_SESSION['latest_blog_id'] = $blog->getId();
					$this->redirect(ahref(sprintf('%s/user/index/', $this->registry->language)));
				} catch (Exception $e) {
					$this->data['errors'][] = __('blog_add_failed');
				}
			}
		}
		
		$this->data['pageTitle'] = __('user_title');
		$this->data['records']['limitOffset'] = $limitOffset;
		$this->data['records']['limitFind'] = $limitFind;
		$this->data['user'] = $this->user;
		$this->data['errors'] = array_merge($this->data['errors'], $this->user->error());
		$this->data['meta']['description'] = __('user_meta_description');

		if ( ! $this->registry->request->isAjax()) {
			if (isset($_SESSION['earliest_blog_id']) && isset($_SESSION['latest_blog_id'])) {
				$this->data['records']['blog'] = R::find('blog', 'id>=:earliest_id AND id<=:latest_id ORDER BY stamp DESC', array(':earliest_id' => $_SESSION['earliest_blog_id'], ':latest_id' => $_SESSION['latest_blog_id']));
			} else {
				$this->data['records']['blog'] = R::find('blog', '1 ORDER BY stamp DESC LIMIT ?, ?', array((int)$limitOffset, (int)$limitFind));
			}
			if ( ! empty($this->data['records']['blog'])) {
				$_SESSION['latest_blog_id'] = max(array_keys($this->data['records']['blog']));
				$_SESSION['earliest_blog_id'] = min(array_keys($this->data['records']['blog']));
			} else {
				$_SESSION['latest_blog_id'] = 0;
				$_SESSION['earliest_blog_id'] = 0;
			}
		} else {
			$this->data['records']['blog'] = R::find('blog', 'id<:earliest_id ORDER BY stamp DESC LIMIT :limit', array(':earliest_id' => $_SESSION['earliest_blog_id'], ':limit' => (int)$limitFind));
			if ( ! empty($this->data['records']['blog'])) {
				$_SESSION['earliest_blog_id'] = min(array_keys($this->data['records']['blog']));
			} else {
				$_SESSION['earliest_blog_id'] = 0;
			}
			return $this->template->view('user/posts', $this->data);
		}
		$this->template->view('user/index', $this->data);
	}
	
	/**
	 * returns results of method blog.
	 *
	 * @param int Starting point of record index
	 * @param int Limit number of records to show
	 */
	public function index($limitOffset = 0, $limitFind = self::LIMIT_RECORDS)
	{
		return $this->blog($limitOffset, $limitFind);
	}
	
	/**
	 * displays a users profile when id is not given the current users profile is shown.
	 *
	 * @param mixed $id
	 */
	public function profile($id = 0)
	{
		$this->auth();
		if ( ! $this->permission->granted($this->user, 'index', 'user')) {
			return $this->error(__('error_no_permission'));
		}
		// was a form sent
		if ($this->input->submit) {
		}
		$this->registry->loader->model('addressbook', true);
		if ( ! $id) $id = $this->user->getId();
		$account = R::load('user', $id);
		//$this->data['records']['users'] = R::find('user', '1 ORDER BY name ASC');
		// add breadcrumb
		$this->registry->addBreadcrumb(__('profile'), sprintf('%s/user/profile/', $this->registry->language));
		$this->registry->addBreadcrumb($account->view(), sprintf('%s/user/profile/%s/', $this->registry->language, $account->getId()));
		$this->data['user'] = $this->user;
		$this->data['friends'] = R::related($account, 'user');
		$this->data['record'] = $account;
		$this->data['profile_id'] = $id;
		$this->data['errors'] = array_merge($this->data['errors'], $this->user->error());
		$this->data['meta']['description'] = __('user_meta_description');
		$this->template->view('user/profile', $this->data);
	}

	/**
	 * displays a login form and tries to login the user when a post form was send.
	 */
	public function login()
	{
		if (isset($this->input->submit)) {
			if ($this->user->auth($this->input->login)) {
				$this->redirectToReferer();
			}
			$this->user->import($this->input->login);
		}
		$this->data['pageTitle'] = __('user_title');
		$this->data['goto'] = $this->input->goto;
		$this->data['user'] = $this->user;
		if (isset($_SESSION['logout'])) {
			unset($_SESSION['logout']);
			$this->data['messages'][] = __('user_successfully_logged_out');
		}
		$this->data['errors'] = array_merge($this->data['errors'], $this->user->error());
		$this->data['meta']['description'] = __('user_meta_description');
		$this->template->view('user/login', $this->data);
	}
	
	/**
	 * displays a lostpassword form or the wait page after the user has requested a new pw.
	 */
	public function lostpassword()
	{
		if (isset($this->input->submit)) {
			if ($this->user->lostpassword($this->input->login)) {
				$this->redirect(ahref(sprintf('%s/user/wait', $this->registry->language), true));
			}
			$this->user->import($this->input->login);
		}
		$this->data['pageTitle'] = __('user_title');
		$this->data['user'] = $this->user;
		$this->data['errors'] = array_merge($this->data['errors'], $this->user->error());
		$this->data['meta']['description'] = __('user_meta_description');
		$this->template->view('user/lostpassword', $this->data);
	}
	
	/**
	 * increments the heartbeat counter, looks for new stuff and outputs HTML.
	 *
	 * A call on this method is issued by a js function from core.js. That js decides about
	 * our responseType. If the HTML document of the client has a #response element the
	 * responseType will be 'item', else it will be 'counter'. The counter is just a notification
	 * badge on the clients avatar.
	 *
	 * @param string $responseType
	 * @return void
	 */
	public function heartbeat($responseType = 'items')
	{
		if ( ! isset($_SESSION['heartbeat'])) $_SESSION['heartbeat'] = 0;
		++$_SESSION['heartbeat'];
		$this->registry->logger->log(sprintf('User heartbeat %d', $_SESSION['heartbeat']));
		// lookup stuff and output it
		if ( ! isset($_SESSION['latest_blog_id'])) return;
		// really do it
		$this->data['records']['blog'] = R::find('blog', 'id>:latest_id ORDER BY stamp DESC', array(':latest_id' => $_SESSION['latest_blog_id']));
		if (empty($this->data['records']['blog'])) return;
		if ($responseType == 'counter') {
			echo $_SESSION['blog_counter'] = count($this->data['records']['blog']);	
		} else {
			unset($_SESSION['blog_counter']);
			$_SESSION['latest_blog_id'] = max(array_keys($this->data['records']['blog']));
			$this->template->view('user/posts', $this->data);
		}
		return true;
	}
	
	/**
	 * displays the wait page wait after a user has requested a new password.
	 */
	public function wait()
	{
		$this->data['pageTitle'] = __('user_title');
		$this->data['user'] = $this->user;
		$this->data['errors'] = array_merge($this->data['errors'], $this->user->error());
		$this->data['meta']['description'] = __('user_meta_description');
		$this->template->view('user/wait', $this->data);
	}
	
	/**
	 * displays a form to change users password.
	 *
	 * This action will display a form to get a new password. This action requires a valid
	 * authorization code which was given on lostpassword action. Without a good code no
	 * action will take place.
	 *
	 * @param string The authorization code to do a password change
	 */
	public function changepassword($authCode = null)
	{
		if (isset($this->input->submit)) {
			if ($this->user->changepassword($this->input->login, $authCode)) {
				$this->redirect(ahref(sprintf('%s/user/login', $this->registry->language), true));
			}
		}
		$this->data['pageTitle'] = __('user_title');
		$this->data['user'] = $this->user;
		$this->data['authCode'] = $authCode;
		$this->data['errors'] = array_merge($this->data['errors'], $this->user->error());
		$this->data['meta']['description'] = __('user_meta_description');
		$this->template->view('user/changepassword', $this->data);
	}
	
	/**
	 * logs out the current session and redirects to login again.
	 */
	public function logout()
	{
		$this->user->logout();
		$this->redirect(ahref(sprintf('%s/user/login', $this->registry->language), true));
	}
}
?>